// 定义一个Trait
pub trait Summary {
    // 定义
    // fn summarize(&self) -> String;
    fn summarize_author(&self) -> String;
    //     默认实现
    fn summarize(&self) -> String{
        // return String::from("(Read more...)");
        format!("(Read more from {}...)", self.summarize_author())
    }
    
}

pub struct NewsArticle {
    pub headline: String,
    pub location: String,
    pub author: String,
    pub content: String,
}

// 实现Trait
impl Summary for NewsArticle {
    fn summarize_author(&self) -> String {
        format!("@{}", self.author)
    }
    fn summarize(&self) -> String {
        format!("{}, by {} ({})", self.headline, self.author, self.location)
    }
}

pub struct Tweet {
    pub username: String,
    pub content: String,
    pub reply: bool,
    pub retweet: bool,
}

// 实现Trait
impl Summary for Tweet {
    fn summarize_author(&self) -> String {
        format!("@{}", self.username)
    }
    
}

// 把trait作为参数
pub fn notify(item: &impl Summary) {
    println!("Breaking news! {}", item.summarize());
}
// 他的完整代码为
pub fn notify2<T: Summary>(item: &T) {
    println!("Breaking news! {}", item.summarize());
}

//多个 trait 约束
pub fn notify3(item1: &impl Summary, item2: &impl Summary) {
    println!("Breaking news! {}, {}", item1.summarize(), item2.summarize());
}
//两个trait 相同类型
pub fn notify4<T: Summary>(item1: &T, item2: &T) {
    println!("Breaking news! {}, {}", item1.summarize(), item2.summarize());
}
// 多个 trait，不同类型
//
pub fn notify5<T: Summary,U: Summary>(item1: &T, item2: &U) {
    println!("Breaking news! {}, {}", item1.summarize(), item2.summarize());
}

pub trait Display {
    fn fmt(&self){
        println!( "Display");
        
    }
}

pub fn notify6(item: &(impl Summary + Display)) {
    println!("Breaking news! {}", item.summarize());

}

pub fn returns_summarizable() -> impl Summary {
    Tweet {
        username: String::from("horse_ebooks"),
        content: String::from(
            "of course, as you probably already know, people"
        ),
        reply: false,
        retweet: false,
    }
}
